/************************************************************************
 * SDL_Layer - A layered display mechanism for SDL
 * Copyright (C) 2008  Julien CLEMENT
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ************************************************************************/

#include "SDL_Layer.h"
#include "SDL_image.h"
#include "libgen.h"

// Include images
/*#include "canyon.xpm"
#include "cloud.xpm"
#include "demo.xpm"
*/

#define W	(640)
#define H	(480)

#define VPX (100)
#define VPY (100)
#define VPW	(W - 2*VPX)
#define VPH (H - 2*VPY)

static int disp_rect_flag = 0;
static int region_flag    = 0;

static void print_gpl_message (const char * program)
{

    const char * msg = "\n\n%s  Copyright (C) 2008  Julien CLEMENT\n"
    "This program comes with ABSOLUTELY NO WARRANTY;\n"
    "This is free software, and you are welcome to redistribute it\n"
    "under certain conditions;.\n\n"
	;

	printf (msg, basename((char *)program));

}

static void print_infos (void)
{
   const char * msg = "\n\n"
		      "** I need your feedbacks to improve SDL_Layer, correct bugs, and know in which projects it is used.\n"
		      "** Don't forget to send me a short email at: andematunum@gmail.com\n"
		      "**\n"
		      "** Many thanks\n";
   printf (msg);
}

static void splash (void) {
	printf ("SDL_Layer Scrolling demo:\n");
	printf ("\n");
	printf ("- Escape to quit\n");
	printf ("- Move mouse to scroll (stop scrolling by moving the mouse to the center of the screen)\n");
	printf ("- Press keypad 0,1,2 to show/hide a specific layer.\n");
	printf ("- Press spacebar to switch to 800x600 (not optimal, clipped to a 640x480 viewport)\n");
	printf ("- Press 'f' to switch between fullscreen and windowed modes.\n");
	printf ("- Press 'r' to switch between whole screen projection and area projection (SDLayer_SetDisplayRect)\n");
	printf ("- Press 'g' to set/unset a region\n");
	printf ("\n");
	printf ("Best viewed at 640x480 resolution.\n");
	//printf ("EnJoY ! (press the ENTER key to start)\n");
	//printf ("\n");
}

int main (int argc, char ** argv)
{

	SDL_Surface * screen;
	SDL_Surface * canyon, * demo, * cloud;
	SDLayer_Display * ld;
	SDL_Rect rect;
	int finished = 0;
	int w[3], h[3];

	print_gpl_message(argv[0]);

	SDL_Init(SDL_INIT_VIDEO);
	atexit (SDL_Quit);
	atexit (print_infos);

/*	canyon = IMG_ReadXPMFromArray(canyon_xpm);
	demo   = IMG_ReadXPMFromArray(demo_xpm);
  cloud  = IMG_ReadXPMFromArray(cloud_xpm);
  */
  canyon = IMG_Load("canyon.jpg");
  demo = IMG_Load("demo.png");
  cloud = IMG_Load("cloud.jpg");

  if ( (canyon == NULL) || (demo == NULL) || (cloud == NULL) )
	{
		fprintf (stderr,
		"One of the necessary resources is missing. Are you in the \"demos\" subdirectory ?\n");
		exit (-1);
	}

	splash();
	/*fflush(stdin);
	char c;
	c = getchar();
  */

	screen = SDL_SetVideoMode(W, H, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);

	if ( screen == (SDL_Surface *)0 )
	{
		fprintf (stderr,
		"Cannot switch to resolution 640x480@32 HWSURFACE|DOUBLEBUF\n");
		fprintf (stderr,
		"Trying 800x600\n");
		screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
		
		if ( screen == (SDL_Surface *)0 )
		{
			fprintf (stderr,
		"Cannot switch to 800x600@32 HWSURFACE|DOUBLEBUF\n");
			fprintf (stderr,
		"Trying a default (not optimized) windowed 640x480 mode\n");
			screen = SDL_SetVideoMode(640, 480, 0, SDL_SWSURFACE);

			if ( screen == (SDL_Surface *)0 ) {
				fprintf (stderr, "All attempts to get a graphical context failed. Aborting.\n");
				exit (-1);
			}
		}
	} else {
		printf ("Optimal mode [OK]\n");
	}

	/* Canyon */
	w[0] = 800;
	h[0] = 600;

	/* D E M O */
	w[1] = 3200;
	h[1] = 1920;

	/* Clouds */
	w[2] = 1920;
	h[2] = 1200;

	ld = SDLayer_CreateRGBLayeredDisplay (SDL_ANYFORMAT, SDLAYER_FLIP,
					      3, w, h, 32, 0, 0, 0, 0);

	if ( ld == NULL )
	{
	fprintf (stderr,
	"Failed to create an RGB layered display.\n");
	exit (-1);
	}

	rect.x = 0;
	rect.y = 0;
	rect.w = 800;
	rect.h = 600;
	
	SDLayer_Blit (canyon, &rect, ld, &rect, 0);

	rect.w = 1920;
	rect.h = 1200;
	SDLayer_Blit (cloud, &rect, ld, &rect,  2);

	rect.w = 3200;
	rect.h = 1920;
	SDLayer_Blit (demo, &rect, ld, &rect,   1);

	SDL_SetAlpha(SDLayer_GetLayer(ld,2), SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT + 100);
	SDL_SetAlpha(SDLayer_GetLayer(ld,1), SDL_SRCALPHA, SDL_ALPHA_TRANSPARENT + 32);

	SDL_FreeSurface (canyon);
	SDL_FreeSurface (demo);
	SDL_FreeSurface (cloud);
	
	SDL_WarpMouse (screen->w/2, screen->h/2);

	SDLayer_SetScrollingFactor(ld, 2, 1.0);
	SDLayer_SetScrollingFactor(ld, 1, 2.0);
	SDLayer_SetScrollingFactor(ld, 0, 0.125);
	
	SDL_Event evt;
	/* Visibility flags */
	int vis0 = 1, vis1 = 1, vis2 = 1;
	Sint16 vpx = 0, vpy = 0, dx = 0, dy = 0;


	/* Region rectangle */
	SDL_Rect reg;

	reg.x = 0;
	reg.y = 0;
	reg.w = 1920;
	reg.h = 600;

	for ( ; finished == 0 ; )
	{
		while ( SDL_PollEvent(&evt) > 0 )
		{

			if (evt.type == SDL_KEYDOWN)
			{

				switch (evt.key.keysym.sym)
				{
					case SDLK_KP0:
						vis0 = (vis0 != 0) ?  (0) : (1);
						SDLayer_SetVisible(ld, 0,  vis0);
						printf ("Layer 0 visibility: %d\n", vis0);
						break;

					case SDLK_KP1:
						vis1 = (vis1 != 0) ?  (0) : (1);
						SDLayer_SetVisible(ld, 1,  vis1);
						printf ("Layer 1 visibility: %d\n", vis1);
						break;

					case SDLK_KP2:
						vis2 = (vis2 != 0) ?  (0) : (1);
						SDLayer_SetVisible(ld, 2,  vis2);
						printf ("Layer 2 visibility: %d\n", vis2);
						break;
		
					case SDLK_ESCAPE:
						finished = 1;
						break;

					case SDLK_SPACE:
						screen = SDL_SetVideoMode(800, 600, 32,
									SDL_ANYFORMAT);//SDL_HWSURFACE|SDL_DOUBLEBUF);
						if ( screen == (SDL_Surface *)0 )
						{
							printf ("Switch to optimal 800x600 failed, trying a default 800x600 mode\n");
							screen = SDL_SetVideoMode(800, 600, 32,
									SDL_ANYFORMAT);
							if ( screen == (SDL_Surface *)0 )
							{
								printf ("Unable to find a suitable 800x600 mode\n");
								finished = 1;
							}
						} else {
							printf ("Optimal 800x600 mode [OK]\n");
						}
						break;

					case SDLK_f:
						SDLayer_ToggleFullScreen(ld);
						break;

					case SDLK_r:
						if (disp_rect_flag == 0) {
								/* Change the display rectangle */
								SDL_Rect clip;
								clip.x = VPX;
								clip.y = VPY;
								clip.w = VPW;
								clip.h = VPH;
								SDLayer_SetDisplayRect (ld, &clip);
								disp_rect_flag = 1;
						} else {
								SDLayer_UnsetDisplayRect (ld);
								disp_rect_flag = 0;
						}
						break;

					case SDLK_g:
						if (region_flag == 0) {
								SDLayer_SetRegion(ld, 2, &reg);
								region_flag = 1;
						} else {
								SDLayer_UnsetRegion(ld, 2);
								region_flag = 0;
						}
						break;


					default:
						break;
				}

			}
			else if (evt.type == SDL_MOUSEMOTION)
			{
				if ( evt.motion.x > 400 ) dx = 1;
				else if ( evt.motion.x < 200 ) dx = -1;
				else dx = 0;

				if ( evt.motion.y > 300 ) dy = 1;
				else if ( evt.motion.y < 200 ) dy = -1;
				else dy = 0;
			}
			else if (evt.type == SDL_MOUSEBUTTONDOWN)
			{
				Sint16	x;
				Sint16  y;
				int k;
				
				printf ("\n");			
				for (k = 0; k < 3; k++ ) {
					SDLayer_GetLayerCoordinates (ld, &x, &y, evt.motion.x, evt.motion.y, k);
					printf ("Coordinates in layer %d: (%d,%d)\n", k, x, y);
				}			

			}
		}

		if ( dx > 0 ) { vpx ++; }
		else if ( dx < 0 ) vpx --;
	
		if ( dy > 0 ) vpy ++;
		else if ( dy < 0 ) vpy --;

		if ( dx || dy )
		{
			/* Clip viewport */
			if ( vpx < 0 ) vpx = 0;
			if ( vpy < 0 ) vpy = 0;
			if ( vpx > (1920-VPW) ) vpx = 1920-VPW;
			if ( vpy > (1200-VPH) ) vpy = 1200-VPH;

			SDLayer_SetViewport (ld, vpx, vpy);
		}

		SDLayer_Update(ld);
	}

	SDLayer_FreeLayeredDisplay(ld);

	exit(-1);

}

